package common;

import java.io.IOException;
import java.util.*;

public final class EDUBOX_Crypto
{
 static String SKEY = "EDUBOXHRD";
 static boolean KEY_TRANS = false;
 
 
 private final static char encodeTable[] = { 
	 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 
	 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 
	 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
	 '+', '/' 
	 }; 
	 private final static byte decodeTable[] = { 
	 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
	 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 
	 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 
	 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 
	 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, 
	 -1, -1 
	 }; 


	 //------------------------------------------------------------------------------------------------------------ 
	 // Methods 
	 //------------------------------------------------------------------------------------------------------------ 
	 /** 
	 * Base 64 문자열을 디코딩한다. 
	 * 
	 *@param s Base 64로 인코딩 되어 있는 문자열 
	 *@return 디코딩된 문자열 
	 */ 
	 private static String base64Decode( String s ) { 
	 StringBuffer stringbuffer = new StringBuffer(); 
	 int i = s.length(); 
	 int j = 0; 
	 int k = 0; 
	 int l = 0; 
	 if ( i % 4 != 0 ) { 
	 throw new IllegalArgumentException( "Not a multiple of 4 characters" ); 
	 } 
	 for ( ; i > 0 && s.charAt( i - 1 ) == '='; i-- ) { 
	 ; 
	 } 
	 if ( s.length() - i > 2 ) { 
	 throw new IllegalArgumentException( "Too many trailing =" ); 
	 } 
	 for ( ; j < i; j++ ) { 
	 char c = s.charAt( j ); 
	 byte byte0 = c >= '\200' ? -1 : decodeTable[c]; 
	 if ( byte0 < 0 ) { 
	 throw new IllegalArgumentException( "Illegal character" ); 
	 } 
	 k = k << 6 | byte0; 
	 if ( ( l += 6 ) >= 8 ) { 
	 l -= 8; 
	 stringbuffer.append( ( char ) ( 0xff & k >> l ) ); 
	 } 
	 } 
	 return stringbuffer.toString(); 
	 } 


	 	/** 
	 	* 일반 문자열을 Base 64로 인코딩한다. 
	 	* 
	 	*@param 인코딩할 일반 문자열 
	 	*@return Base 64로 인코딩된 문자열 
	 	*/ 
	 private static String base64Encode( String s ) { 
	 	StringBuffer stringbuffer = new StringBuffer(); 
	 		int i = s.length(); 
	 		int j = 0; 
	 		int k = 0; 
	 		try{
	 			for ( int l = 0; l < i; l++ ) { 
	 				char c = s.charAt( l );

//	 			if ( (int) c >= (int) '?' ) { 
//	 				throw new IllegalArgumentException( "Illegal character" ); 
//	 			} 
		 			j = j << 8 | c; 
		 			for ( k += 8; k >= 6; ) { 
		 				k -= 6; 
		 				stringbuffer.append( encodeTable[0x3f & j >> k] ); 
		 			} 
		 		} 
		 		switch ( k ) { 
		 			case 2: 
		 				// '\002' 
		 				stringbuffer.append( encodeTable[0x3f & j << 4] ); 
		 				stringbuffer.append( '=' ); 
		 				stringbuffer.append( '=' ); 
		 			break; 
		 			case 4: 
		 				// '\004' 
		 				stringbuffer.append( encodeTable[0x3f & j << 2] ); 
		 				stringbuffer.append( '=' ); 
		 			break; 
		 		} 
	 		}catch ( Exception e ) {
	 			throw new IllegalArgumentException( "Illegal character" ); 
	 		}
		            
	 		return stringbuffer.toString(); 
	 	} 


	 private static String Cross_IP(String aData, String u_ip) { 
	if ((aData == null) || (aData.length() == 0)) 
        throw new IllegalArgumentException("ERROR MSG : Cross Data Null."); 
	String return_value ;
	aData = SKEY + getDateTime(0) + aData + SKEY;
	char[] data = new char[aData.length()];
	char temp ;
	for(int i=0;i<aData.length();i++) data[i] = aData.charAt(i);
	int[] key = new int[4];
	key = getIPKey(u_ip);
	for (int j = 0; j < key.length; j++){
		for(int i=0; i < data.length; i= i + key[j]){
			temp = data[0];
			data[0] = data[i];
			data[i] = temp;
		}
	}
//	return_value = data.toString();
	return_value = new String(data);
	return return_value;
}
	 private static String UpCross_IP(String aData, String u_ip) { 
	if ((aData == null) || (aData.length() == 0)) 
        throw new IllegalArgumentException("ERROR MSG : UnCross Data Null."); 
	char[] data = new char[aData.length()];
	char temp ;
	String return_value = "";
	for(int i=0;i<aData.length();i++){data[i] = aData.charAt(i);}
	
	int[] key = new int[4];
	int startpointer = 0;
	key = getIPKey(u_ip);
	for (int j = key.length -1; j >= 0; j--){
		int step = 0;
		startpointer = (int)(key[j] * (Math.floor((data.length-1) / key[j])));
		step = key[j]; 
		for (int i = startpointer ; i >= step;i = i-step){
			temp = data[i];
			data[i] = data[0];
			data[0] = temp;
			return_value = new String(data);
		}		
	}
	
	return_value = new String(data);
	if (return_value.length() > (SKEY.length() * 2) + 10){
		if (return_value.substring(return_value.length() - SKEY.length(), return_value.length()).equals(SKEY)){
			if (return_value.substring(0, SKEY.length()).equals(SKEY)){
				return_value = return_value.substring(SKEY.length(), return_value.length() - SKEY.length());
				String date_value = return_value.substring(0, 10); 
				if (date_value.equals(getDateTime(-1)) || date_value.equals(getDateTime(0)) || date_value.equals(getDateTime(1))){
					return_value = return_value.substring(10,return_value.length());
				}else{
					System.out.println("UnCross ERROR : Time Value Over = "+ return_value);
					return_value = "";
				}
			}else{
				System.out.println("UnCross ERROR : First SKEY Value BAD = "+ return_value);
				return_value = "";
			}
		}else{
			System.out.println("UnCross ERROR : Last SKEY Value BAD = "+ return_value);
			return_value = "";
		}
	}else{
		System.out.println("UnCross ERROR : Value Length BAD = "+ return_value);
		return_value = "";
	}
	return return_value;
}
	 private static int[] getIPKey(String u_ip){
	if ((u_ip == null) || (u_ip.length() == 0)) 
        throw new IllegalArgumentException("Can not u_ip string.");
	int n = 0;
	String[] temp_ip = new String[u_ip.length()];
	for (int i=0;i<u_ip.length();i++) temp_ip[i] = u_ip.substring(i,i+1);
	int[] key = new int[]{0,0,0,0};
	for (int i=0;i < temp_ip.length;i++){
		if (!".".equals(temp_ip[i])){
			key[n] = (key[n] + Integer.parseInt(temp_ip[i])) % 10;
		}else{
			n++;
		}
	}
	for (int i=0;i < key.length;i++){
		if (key[i] == 0 ){ key[i] = 3;}
		if (key[i] == 1 ){ key[i] = 5;}
	}
	return key;
	
}
	 private static String getDateTime(int hour){
	String this_Year;
	String this_Month;
	String this_Day;
	String this_Hour;
	String return_value = "";
	Calendar cal = Calendar.getInstance();
	cal.add(Calendar.HOUR, hour);
	this_Year = Integer.toString(cal.get(cal.YEAR));
	this_Month = ((cal.get(cal.MONTH)+1) > 9) ? Integer.toString(cal.get(cal.MONTH)+1) : "0" + Integer.toString(cal.get(cal.MONTH)+1) ;
	this_Day = (cal.get(cal.DATE) > 9) ? Integer.toString(cal.get(cal.DATE)) : "0" + Integer.toString(cal.get(cal.DATE));
	this_Hour = (cal.get(cal.HOUR_OF_DAY) > 9) ? Integer.toString(cal.get(cal.HOUR_OF_DAY)) : "0" + Integer.toString(cal.get(cal.HOUR_OF_DAY));
	return_value = this_Year+ this_Month + this_Day + this_Hour;
	return return_value ; 
}
public static String Encode(String invalue,  String u_ip){
	if(KEY_TRANS){
		try{
			invalue = new String(invalue.getBytes("KSC_5601"), "8859_1");
		}catch(Exception e){
			System.out.println("     : [trans_err]        ==> " + e);
		}
	}
	String value = "";
	value = base64Encode(invalue);
	value = Cross_IP(value, u_ip);

	return value;
}
public static String Decode(String invalue,  String u_ip){
	String value = "";
	if (invalue.length() > (SKEY.length() * 2) + 10){
		value = UpCross_IP(invalue, u_ip);
		if (!value.equals("")) value = base64Decode(value);
	}
	
	if(KEY_TRANS){
		try{
			value = new String(value.getBytes("8859_1"), "KSC_5601");
		}catch(Exception e){
			System.out.println("     : [trans_err]        ==> " + e);
		}
	}
	return value;
}

public static void setTrans_true(){
	KEY_TRANS = true;	
}

public static void setTrans_false(){
	KEY_TRANS = false;	
}

private static String Cross_Time(String aData, String thisTime) { 
	if ((aData == null) || (aData.length() == 0)) 
        throw new IllegalArgumentException("ERROR MSG : Cross Data Null."); 
	String return_value ;
	aData = SKEY + thisTime + aData + SKEY;
	char[] data = new char[aData.length()];
	char temp ;
	for(int i=0;i<aData.length();i++) data[i] = aData.charAt(i);
	int[] key = new int[thisTime.length()];
	key = getTimeKey(thisTime);
	for (int j = 0; j < key.length; j++){
		for(int i=0; i < data.length; i= i + key[j]){
			temp = data[0];
			data[0] = data[i];
			data[i] = temp;
		}
	}
	return_value = new String(data);
	return return_value;
}

private static String UpCross_Time(String aData, String thisTime) { 
	if ((aData == null) || (aData.length() == 0)) 
        throw new IllegalArgumentException("ERROR MSG : UnCross Data Null."); 
	char[] data = new char[aData.length()];
	char temp ;
	String return_value = "";
	for(int i=0;i<aData.length();i++){data[i] = aData.charAt(i);}
	
	int[] key = new int[thisTime.length()];
	int startpointer = 0;
	key = getTimeKey(thisTime);
	for (int j = key.length -1; j >= 0; j--){
		int step = 0;
		startpointer = (int)(key[j] * (Math.floor((data.length-1) / key[j])));
		step = key[j]; 
		for (int i = startpointer ; i >= step;i = i-step){
			temp = data[i];
			data[i] = data[0];
			data[0] = temp;
			return_value = new String(data);
		}		
	}
	
	return_value = new String(data);
	if (return_value.length() > (SKEY.length() * 2) + 10){
		if (return_value.substring(return_value.length() - SKEY.length(), return_value.length()).equals(SKEY)){
			if (return_value.substring(0, SKEY.length()).equals(SKEY)){
				return_value = return_value.substring(SKEY.length(), return_value.length() - SKEY.length());
				String date_value = return_value.substring(0, 10); 
				if (date_value.equals(thisTime)){
					return_value = return_value.substring(10,return_value.length());
				}else{
					System.out.println("UpCross_Time ERROR : Time Value Over = "+ return_value);
					return_value = "";
				}
			}else{
				System.out.println("UpCross_Time ERROR : First SKEY Value BAD = "+ return_value);
				return_value = "";
			}
		}else{
			System.out.println("UpCross_Time ERROR : Last SKEY Value BAD = "+ return_value);
			return_value = "";
		}
	}else{
		System.out.println("UpCross_Time ERROR : Value Length BAD = "+ return_value);
		return_value = "";
	}
	return return_value;
}
private static int[] getTimeKey(String TimeKey){
	if ((TimeKey == null) || (TimeKey.length() == 0)) 
        throw new IllegalArgumentException("Can not TimeKey string.");
	int[] TempTimeKey = new int[TimeKey.length()];
	for (int i=0;i<TimeKey.length();i++) TempTimeKey[i] = Integer.parseInt(TimeKey.substring(i,i+1));

	for (int i=0;i < TempTimeKey.length;i++){
		if (TempTimeKey[i] == 0 ){ TempTimeKey[i] = 3;}
		if (TempTimeKey[i] == 1 ){ TempTimeKey[i] = 5;}
	}
	return TempTimeKey;
}
public static String Encode2(String invalue){
	if(KEY_TRANS){
		try{
			invalue = new String(invalue.getBytes("KSC_5601"), "8859_1");
		}catch(Exception e){
			System.out.println("     : [trans_err]        ==> " + e);
		}
	}
	String value = "";
	value = base64Encode(invalue);
	String thisTime = getDateTime(0);
	value = Cross_Time(value, thisTime);
	thisTime = base64Encode(thisTime);
	String thisTime_len = Integer.toString(thisTime.length());
	String thisTime_len2 = Integer.toString(thisTime_len.length());
	String value_len = Integer.toString(value.length());
	String value_len2 = Integer.toString(value_len.length());
	value =  value_len2 + value_len + thisTime_len2  + thisTime_len + value + thisTime;
	value = value.replace("=", "_");
	return value;
}
public static String Decode2(String invalue){
	String value = "";
	String thisTime = "";
	int time_len,time_pos = 0;
	int data_len,data_pos = 0;
	String nowTime = getDateTime(0);
	int DelayTime = 5;

	try{
		if (invalue.length() > (SKEY.length() * 2) + 10){
			invalue = invalue.replace("_", "=");
			data_pos =  Integer.parseInt(invalue.substring(0,1));
			data_len =  Integer.parseInt(invalue.substring(1,data_pos+1));
			invalue = invalue.substring(data_pos+1, invalue.length());
			time_pos =  Integer.parseInt(invalue.substring(0,1));
			time_len =  Integer.parseInt(invalue.substring(1,time_pos+1));
			invalue = invalue.substring(time_pos+1, invalue.length());
			thisTime = invalue.substring(data_len,data_len+time_len);
			invalue = invalue.substring(0,data_len);
			thisTime = base64Decode(thisTime);
			// 시간 비교
			int nowTimeInt, thisTimeInt = 0;
//			int nowY,nowM,nowD,nowH = 0;
//			int thisY,thisM,thisD,thisH = 0;

			nowTimeInt = (((Integer.parseInt(nowTime.substring(0,4)) * 12) * 30) * 24) + ((Integer.parseInt(nowTime.substring(4,6)) * 30)  * 24) + (Integer.parseInt(nowTime.substring(6,8)) * 24)  + Integer.parseInt(nowTime.substring(8,10));
			thisTimeInt = (((Integer.parseInt(thisTime.substring(0,4)) * 12) * 30) * 24) + ((Integer.parseInt(thisTime.substring(4,6)) * 30)  * 24) + (Integer.parseInt(thisTime.substring(6,8)) * 24)  + Integer.parseInt(thisTime.substring(8,10));
			if ((nowTimeInt - DelayTime) <= thisTimeInt &&  (nowTimeInt + 1) >= thisTimeInt){
				value = UpCross_Time(invalue, thisTime);
			}else{
				System.out.println("Time Key Value Time Out Error");
				value = "";
			}
			if (!value.equals("")) value = base64Decode(value);
		}
		if(KEY_TRANS){
			try{
				value = new String(value.getBytes("8859_1"), "KSC_5601");
			}catch(Exception e){
				System.out.println("     : [trans_err]        ==> " + e);
			}
		}
	}catch(Exception e){
		System.out.println("Decoding Type Error");
	}
	return value;
}
}